<!--
 * @Author: wusd
 * @Date: 2022-05-19 09:51:02
 * @LastEditors: wusd
 * @LastEditTime: 2024-08-26 09:19:18
 * @Description: 
 * 
-->
<script lang="tsx">
import { Component, Vue, Prop, Model, Watch } from 'vue-property-decorator'
import { WFormConfig } from 'types/form'
import { AnyObj } from 'types/common'
import { CreateElement } from 'vue'
import { renderFormElement } from '@/untils/renderFunction'
import { fixShowValue, mergeObject, mergeSingleObject } from '@/untils'
@Component({
  name: 'WForm'
})
export default class WForm extends Vue {
  @Model('input', { type: Object }) public value: any

  @Prop({
    default: () => ({
      columns: []
    }),
    type: Object
  })
  formConfig!: WFormConfig
  isFirstInit = true
  @Watch('value', { deep: true, immediate: true })
  changeValue(newValue: any) {
    newValue = JSON.parse(JSON.stringify(newValue))
    if (newValue?.$fromRender) {
      this.formData[newValue.$fromRender.prop] = newValue.$fromRender.value
      /**
       * 防止在表单元素变更的同时设置model对象中其他属性导致的数据没存入问题
       * 例如：el-select组件，变更时change事件改变了model对象中的值，同时设置model对象中其他属性
       */
      // mergeSingleObject(this.formData, newValue)
      delete newValue.$fromRender
      // delete this.formData.$fromRender
    } else {
      if (this.isFirstInit) {
        this.formData = JSON.parse(JSON.stringify(newValue))
        this.isFirstInit = false
      } else {
        mergeSingleObject(this.formData, newValue)
      }
      delete newValue.$fromRender
    }
  }
  @Watch('formConfig', { deep: true, immediate: true })
  changeConfig() {
    this.init()
  }

  public formData: AnyObj = {}
  public formRules: AnyObj = {}

  /** 初始化各类数据 */
  public async init() {
    /**合并配置项 */
    mergeObject(this.formConfig, Vue.prototype?.$baseConfig?.pageConfig.formConfig)
    this.formConfig?.columns?.forEach(async item => {
      if (item.apiList) {
        item.list = await item.apiList()
      }
    })
    /** 初始化表单验证 */
    let formRules: AnyObj = {}
    this.formConfig.columns?.map(item => {
      formRules[item.prop] = item.rules
    })
    this.formRules = formRules
  }

  protected render(h: CreateElement) {
    return (
      <el-form
        {...this.formConfig?.nodeData}
        ref="w_form"
        class="w_form"
        props={{
          model: this.formData
        }}
        rules={this.formRules}
        label-width={this.formConfig?.labelWidth || '80px'}>
        {this.formConfig.columns
          ?.filter(item => {
            return fixShowValue({}, item.show)
          })
          .map(item => {
            return (
              <el-col span={item.span || 24}>
                <el-form-item
                  class={`w_form_item_${item.prop}`}
                  prop={item.prop}
                  label={item.label}
                  label-width={item?.labelWidth || this.formConfig?.labelWidth}>
                  {renderFormElement(h, {
                    config: item,
                    valueClass: 'w_form_item_value',
                    model: this.formData,
                    _this: this
                  })}
                </el-form-item>
              </el-col>
            )
          })}
      </el-form>
    )
  }
}
</script>

<style lang="scss" scoped>
.w_form {
  .w_form_item_value {
    width: 100%;
  }
}
</style>
